﻿using System;
using System.Text.RegularExpressions;
using Krilib.Data;

namespace Krile.Data
{
    public abstract class DefaultSearchDataBase : SearchData
    {
        public bool IsSearchDataMatched(string haystack)
        {
            if (Arguments.Length == 0) return Exclude;
            switch (this.SearchType)
            {
                case SearchTypes.Perfect:
                    if (string.Compare(haystack, Arguments, IgnoreCase) == 0)
                        return !Exclude;
                    break;
                case SearchTypes.Prefix:
                    if (haystack.StartsWith(Arguments,
                        IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture))
                        return !Exclude;
                    break;
                case SearchTypes.Backward:
                    if (haystack.EndsWith(Arguments,
                        IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture))
                        return !Exclude;
                    break;
                case SearchTypes.Regex:
                    if (Regex.Match(haystack, Arguments).Success)
                        return !Exclude;
                    break;
                case SearchTypes.Partial:
                default:
                    if (haystack.Contains(Arguments))
                        return !Exclude;
                    break;
            }
            return Exclude;
        }

        public enum SearchTypes
        {
            Partial = 0,
            Prefix,
            Backward,
            Perfect,
            Regex
        };

        public sealed override bool Exclude { get; set; }

        public sealed override Krilib.Control.SDataArgSetUI GetArgSetUI()
        {
            return new Data.DSDataArgSetUI(this);
        }

        public string Arguments { get; set; }

        public bool IgnoreCase { get; set; }

        public SearchTypes SearchType { get; set; }

        public string GetCurrentSearchTypeName()
        {
            switch (SearchType)
            {
                case SearchTypes.Partial:
                    return Lang.DSData.SType_Partial;
                case SearchTypes.Prefix:
                    return Lang.DSData.SType_Prefix;
                case SearchTypes.Backward:
                    return Lang.DSData.SType_Backward;
                case SearchTypes.Perfect:
                    return Lang.DSData.SType_Perfect;
                case SearchTypes.Regex:
                    return Lang.DSData.TYPE_Regex;
                default:
                    return "Invalid";
            }
        }

        public sealed override void ReadXml(System.Xml.XmlReader reader)
        {
            int nsResult;
            if (int.TryParse(reader.GetAttribute("Type"), out nsResult))
                SearchType = (SearchTypes)nsResult;
            bool icResult;
            if (bool.TryParse(reader.GetAttribute("IgnoreCase"), out icResult))
                IgnoreCase = icResult;
            reader.ReadStartElement();
            Arguments = reader.ReadElementString("Argument");
            base.ReadXml(reader);
        }

        public sealed override void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteAttributeString("Type", ((int)SearchType).ToString());
            writer.WriteAttributeString("IgnoreCase", IgnoreCase.ToString());
            writer.WriteElementString("Argument", Arguments);
            base.WriteXml(writer);
        }
    }

    public class TextSearchData : DefaultSearchDataBase
    {
        public TextSearchData() { }

        public TextSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Partial;
            this.Exclude = false;
        }

        public override string Description
        {
            get { return Lang.DSData.Text_Desc + ": " + Arguments + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_TEXT"; }
        }

        public override bool IsMatched(Status status)
        {
            return IsSearchDataMatched(status.text.Original);
        }

        public override string Name
        {
            get { return Lang.DSData.Text_Name; }
        }

        public override object Clone()
        {
            var newsd = new TextSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }
    }

    public class UserSearchData : DefaultSearchDataBase
    {
        public UserSearchData() { }

        public UserSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Partial;
            this.Exclude = false;
        }

        public override string Description
        {
            get { return Lang.DSData.User_Desc + ": " + Arguments + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_USER"; }
        }

        public override bool IsMatched(Status status)
        {
            return IsSearchDataMatched(status.user.name);
        }

        public override string Name
        {
            get { return Lang.DSData.User_Name; }
        }

        public override object Clone()
        {
            var newsd = new UserSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }
    }

    public class UserIdSearchData : DefaultSearchDataBase
    {

        public UserIdSearchData() { }

        public UserIdSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Perfect;
            this.Exclude = false;
        }

        public override string Description
        {
            get { return Lang.DSData.UId_Desc + ": " + Arguments + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_USERID"; }
        }

        public override bool IsMatched(Status status)
        {
            return IsSearchDataMatched(status.user.id);
        }

        public override string Name
        {
            get { return Lang.DSData.UId_Name; }
        }

        public override object Clone()
        {
            var newsd = new UserIdSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }
    }

    public class ServiceIdSearchData : DefaultSearchDataBase
    {
        public ServiceIdSearchData() { }

        public ServiceIdSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Perfect;
            this.Exclude = false;
        }

        
        public override string Description
        {
            get { return Lang.DSData.SvcId_Desc + ": " + Arguments + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_SVCID"; }
        }

        public override bool IsMatched(Status status)
        {
            return IsSearchDataMatched(status.ParentService.Id);
        }

        public override string Name
        {
            get { return Lang.DSData.SvcId_Name; }
        }

        public override object Clone()
        {
            var newsd = new ServiceIdSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }
    }

    public class ServiceSearchData : DefaultSearchDataBase
    {
        public ServiceSearchData() { }

        public ServiceSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Perfect;
            this.Exclude = false;
        }


        public override string Description
        {
            get { return Lang.DSData.Svc_Desc + ": " + Arguments + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_SVC"; }
        }

        public override bool IsMatched(Status status)
        {
            return IsSearchDataMatched(status.ParentService.Name);
        }

        public override string Name
        {
            get { return Lang.DSData.Svc_Name; }
        }

        public override object Clone()
        {
            var newsd = new ServiceIdSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }
    }

}
